<?php
/**
 * FastApp.
 * 1/1/25
 * @Author deepsea
 * @Contact (telegram:deepsea159)
 */

namespace App\Fastapp\Api\Service\Crypto\Coin;

use BitcoinPHP\BitcoinECDSA\BitcoinECDSA;
use GuzzleHttp\Client;
use Mine\Helper\Str;

class Btc
{
    public static ?Client $client = null;
    const USER = 'deepsea';
    const PASSWORD = 'deepsea';

    const HOST = 'http://127.0.0.1:18443';

    public static function transaction(string $fromAddress, string $toAddress, int|float $amount): array
    {
        $res = self::getUtox($fromAddress, $amount);
        list($txid, $vout) = $res;
        if (!$txid) return [];
        $signedHex = self::request([
            'method' => 'createrawtransaction',
            'params' => [
                [[
                    'txid' => $txid,
                    'vout' => $vout,
                ]],
                [
                    $toAddress => $amount,
                ]
            ]
        ]);
        $signedTx = self::request([
            'method' => 'signrawtransactionwithwallet',
            'params' => [
                $signedHex
            ]
        ]);
        print_r($signedTx);
        return self::request([
            'method' => 'sendrawtransaction',
            'params' => [$signedTx['hex']]
        ]);
    }

    public static function genAddress(): array
    {
        $bitcoinECDSA = new BitcoinECDSA();
        $bitcoinECDSA->generateRandomPrivateKey(Str::random(31, 0));
        return [$bitcoinECDSA->getAddress(), $bitcoinECDSA->getWif()];
    }

    public static function getUtox(string $address, float|int $targetAmount): array
    {
        $utxos = self::request([
            'method' => 'listunspent',
            'params' => [
                1,
                99999999,
                [$address]
            ]
        ]);
        $filteredUtxos = array_filter($utxos, function ($utxo) use ($targetAmount) {
            return $utxo['amount'] >= $targetAmount && $utxo['spendable'];
        });

        if (empty($filteredUtxos)) {
            throw new \Exception("没有足够的余额或符合条件的 UTXO");
        }

        usort($filteredUtxos, function ($a, $b) {
            return $a['amount'] <=> $b['amount'];
        });

        $selectedUtxo = $filteredUtxos[0];

        // 提取 txid 和 vout
        $txid = $selectedUtxo['txid'];
        $vout = $selectedUtxo['vout'];
        $amount = $selectedUtxo['amount'];
        return [$txid, $vout, $amount];
    }

    public static function request(array $param): mixed
    {
        if (!self::$client) {
            self::$client = new Client([
                'base_uri' => self::HOST,
                'auth' => [self::USER, self::PASSWORD], // 设置认证
                'timeout' => 5.0,
            ]);
        }
        if (empty($param['id'])) $param['id'] = 'ds-' . $param['method'];
        $param['jsonrpc'] = '1.0';
        try {
            $response = self::$client->post('', ['json' => $param]);
            return json_decode($response->getBody()->getContents(), true)['result'];
        } catch (\Throwable $exception) {
            print_r($exception->getMessage());
        }
        return null;
    }
}